
function FirstPersonScene(webglObj){
	
	BuildingScene.call(this);
	
	this.CONSTANTS = {EXTRUDE_CORRIDOR : 0, EXTRUDE_OTHERS: 0, PAREDES: true, TECHO: false, BEVEL_ESCALERAS: false};
	this.STATE = {SHOW_WALLS : false, MOUSE : false}
	
	var _this = this;
	var _webglObj = webglObj;
	var _scene = this.getScene();//TODO ver como hacer esto mejor (herencia)
	var _camera = null;	
	
	this.tipoEscena = "fps";
	this.getPanelsConfiguration = function(){
		var config =
		 {
				 dataRenderer :{ enabled : true, show: false},
				 stats :{ enabled : true, show: true},
				 contexto :{ enabled : true, show: false},
				 animacion :{ enabled : false, show: false},
				 camara :{ enabled : true, show: true},
				 ubicacion :{ enabled : true, show: true},
				 tab_busqueda :{ show: false},
				 tab_jerarquia :{ show: true},
				 tree: {animacionOnOff: false, animacion2d3d: false},
		 }
		
		return config
	};
	
	
	this.activate = function(){
		//console.log("FLY2",this.levelsShown, this.activeLevels);
		//CONTROLLER_JERARQUIA_SPACES.setState(this.levelsShown, this.activeLevels);	
//		var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(_ubicacionInicial.edificio, _ubicacionInicial.nivel, true, true);
//		if (obj) ANIMATOR.reposicionarCamaraFromTree(BUILDING_TARGET_POSITION, obj.nivelesActuales , [], false, "level",null, false);
		
		$("#divBotonesFPS").css('display','inline');
		$("#btnControles").show();
		$("#controlesFPS").show();
	}
	
	this.deactivate = function(){
		$("#divBotonesFPS").css('display','none');
		$("#btnControles").hide();
		$("#controlesFPS").hide();
	}
	
	
	var materialBuilder = new MaterialBuilder();
	var meshBuilder = new MeshBuilder(materialBuilder);
	var _objectBuilder = new builderSceneObjects(meshBuilder, materialBuilder, _this);
//	var _objectBuilder = new builderSceneObjects(new MeshBuilder());
	this.getObjectBuilder = function(){
		return _objectBuilder;
	};
	
	
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	
	//RADIO BUTTONS TIPO DE ANIMACION 
	  //RADIO BUTTONS TIPO DE ANIMACION 
	  //RADIO BUTTONS TIPO DE ANIMACION 
	  var contenedorRadios = $("#divRadiosWalls");
	  //cargamos los radio buttons segun los tipos de animacion (definidos en dibujadorCamino.js)
	  
	   arr = [{tipo:"on", name: "ON", desc:"Se muestran las paredes"},
				  {tipo:"off", name: "OFF", desc:"No se muestran las paredes"}];
	   var nameRadiosWalls = "toggleWalls";
	   var valorDefault =  (this.STATE.SHOW_WALLS)? 'on' : 'off';
	   
	  //		 var arr = ANIMATOR.getTiposAnimacion();
	  for (var i = 0, l = arr.length; i<l; i++){
		  r1 = $("<input />").attr({id: 'radio'+nameRadiosWalls+i, type: 'radio', name: nameRadiosWalls,  value: arr[i].tipo});
		  texto = arr[i].name; 
		  $(contenedorRadios).append(r1);
		  
		  var label = $('<label for="radio'+nameRadiosWalls+i+'">'+texto+'</label>');
		  $(contenedorRadios).append(label);
	  }	 
	  
	  //seleccionamos el radio button del tipo de animacion, segun el valor de la configuracion inicial
	  $('input:radio[name='+nameRadiosWalls+'][value='+valorDefault+']:nth(0)').attr('checked',true);
	  $(contenedorRadios).buttonset();
	  
	  //el tooltip hay q asignarselo al label asociado al radio button
	  $( "#" +$(contenedorRadios).attr('id')+ " label" ).each(function(index) {
		  $(this).attr("title",arr[index].desc);
	  });
	  
	  
	  $("input[name="+nameRadiosWalls+"]").change(function(){
		  var val = $("input[name="+nameRadiosWalls+"]:checked").val();
		  if (val == 'on'){ _this.showWalls();}
		  else{ _this.hideWalls(); }
		 
	  });
	  
	  //fin RADIO BUTTONS TIPO DE ANIMACION 
	  //fin RADIO BUTTONS TIPO DE ANIMACION 
	  
	  
	  
	  //RADIO BUTTONS TIPO DE ANIMACION 
	  //RADIO BUTTONS TIPO DE ANIMACION 
	  //RADIO BUTTONS TIPO DE ANIMACION 
	  var contenedorRadios = $("#divFPSMouseOnOff");
	  //cargamos los radio buttons segun los tipos de animacion (definidos en dibujadorCamino.js)
	  
	  arr = [{tipo:"on", name: "ON", desc:"Habilitar controles del mouse"},
	         {tipo:"off", name: "OFF", desc:"Deshabilitar controles del mouse"}];
	  var nameRadios = "toggleFPSMouse";
	  var valorDefault =  (_this.STATE.MOUSE)? 'on' : 'off';
	  
	  //		 var arr = ANIMATOR.getTiposAnimacion();
	  for (var i = 0, l = arr.length; i<l; i++){
		  r1 = $("<input />").attr({id: 'radio'+nameRadios+i, type: 'radio', name: nameRadios,  value: arr[i].tipo});
		  texto = arr[i].name; 
		  $(contenedorRadios).append(r1);
		  
		  var label = $('<label for="radio'+nameRadios+i+'">'+texto+'</label>');
		  $(contenedorRadios).append(label);
	  }	 
	  
	  //seleccionamos el radio button del tipo de animacion, segun el valor de la configuracion inicial
	  $('input:radio[name='+nameRadios+'][value='+valorDefault+']:nth(0)').attr('checked',true);
	  $(contenedorRadios).buttonset();
	  
	  //el tooltip hay q asignarselo al label asociado al radio button
	  $( "#" +$(contenedorRadios).attr('id')+ " label" ).each(function(index) {
		  $(this).attr("title",arr[index].desc);
	  });
	  
	  
	  $("input[name="+nameRadios+"]").change(function(){
		  var val = $("input[name="+nameRadios+"]:checked").val();
		  
		  if (val == 'on'){ _this.STATE.MOUSE = true;}
		  else{ _this.STATE.MOUSE = false; }
		  
	  });
	  
	  //fin RADIO BUTTONS TIPO DE ANIMACION 
	  //fin RADIO BUTTONS TIPO DE ANIMACION 
	  
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	  //-------------------------- UI -------------------------------------
	  
	
	this.showWalls = function(){
		//console.log('show walls')
		this.STATE.SHOW_WALLS = true;
		for (var id in this.objetos3D){//this.objetos3D en BUILDINGSCENE.JS
			this.objetos3D[id].showWalls();
			
		}
	}
	this.hideWalls = function(){
		//console.log('hide walls')
		this.STATE.SHOW_WALLS = false;
		for (var id in this.objetos3D){//this.objetos3D en BUILDINGSCENE.JS
			this.objetos3D[id].hideWalls();
		}
	}
	
	
	
	
	var domContainer = _webglObj.getDomContainer();
	var projector = new THREE.Projector();
	
	//marcadores para mostrar el inicio/fin de una animacion
	var renderer = _webglObj.getRenderer();
	var _meshFlechaInicio = null, 
	_meshFlechaDestino = null; //mesh para la flechas de inicio y fin del camino
	
	var escenaPlanos = null;//escenaPlanos = muestra solo los 3 planos (en gris)
	var escenaCompleta = null;//escenaCompleta = muestra fuente, arboles, autos, etc
	
	var directionalLight, pointLight, ambientLight;	 //luces

	var _camaraFlyContext = null, _camaraFly = null, controls = null;
	
	//+++++++++ PARA DEBUG ++++++++++
	var objPersona; //DEBUG.cubo para debuggear el drag
	this.getDragDebugCube = function(){return objPersona;}//DEBUG.
	//+++++++++ fin PARA DEBUG ++++++++++
	
	
	//DEPRECATED
	var nombreCalles = [];
	this.getNombreCalles = function(){return nombreCalles;};
	//DEPRECATED
	
	//API
	this.addToScene = function(object){_scene.add(object);};
	this.getCamera = function(){return _camera;};
	this.getScene = function(){return _scene;};
	this.getCameraControls = function(){return controls;};
	this.getMarcadorInicio = function(){return _meshFlechaInicio;};
	this.getMarcadorFinal = function(){return _meshFlechaDestino;};
	this.moverContextoEscena = function(altura){escenaPlanos.position.y = altura;};
	this.getContextFlyCamera = function(){return _camaraFlyContext};
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	//------------------------------
	
	this.getPersonControls = function(){
		return personControls;
	}
	var refreshIntervalId = null;
	 var funcionRotacion = function(xNorm, yNorm){
		 //console.log('f')
			var ang1 = -xx/50;
			var ang2 = yy/100;
//			var ang1 = -Math.PI/40 * (xx)*Math.abs(xx);
//			var ang2 = Math.PI/40* (yy)*Math.abs(yy);

			//console.log("no_button", params)
			_this.getPersonControls().rotarHorizontalmente(ang1);
			
			var pitchAng = _this.getPersonControls().anguloPitch;
			var proxPitchAng = pitchAng+ang2;
			if (proxPitchAng < Math.PI/2 && proxPitchAng > -Math.PI/2){
				//console.log('funcionRotacion', proxPitchAng )
				_this.getPersonControls().rotarPitch(ang2);
			}
			
		}
	
	var xx , yy;
	var moviendose = false;
	this.moverse = function(x, y){
		xx = x;
		yy = y;
		if (!moviendose){
			moviendose = true;
			refreshIntervalId = setInterval(funcionRotacion, 20);
		}
	}
	
	this.noMoverse = function(){
		clearInterval(refreshIntervalId);
		moviendose = false;
	}
	
	
	var velocidadAvance = 2;
	var avanzando = false;
	var funcionAvance = function(){
		_this.getPersonControls().desplazarXZ(new THREE.Vector3( 0, 0 , avance), velocidadAvance);//avance == 1 o -1
	};
	var avance = 0;
	var dummyIntervalAvance;
	this.avanzar = function(valor){
		avance = valor;
		if (!avanzando){
			velocidadAvance = 2;
			avanzando = true;
			dummyIntervalAvance = setInterval(funcionAvance, 25);
		}
	}
	
	this.noAvanzar = function(){
		avanzando = false;
		avance = 0;
		clearInterval(dummyIntervalAvance);
	}
	//------------------------------
	
	
	
	
	var SELECTED = 0;
	var inicial = null;
	var lock = false;
	this.handleEvent = function(params){
		
		if (!params || !params.type){return;}
		
		switch(params.type){
			case "mousewheel":
				 
				$(WEBGL.getDomContainer()).css('cursor','');
//				 var vector = new THREE.Vector3( params.xNorm, params.yNorm, 0.5 );
//				 projector.unprojectVector( vector, _camera );
//	
//				 var valor = params.delta *Math.abs(controls.object.position.y/15);
//				 var ray = new THREE.Ray( _camera.position, vector.subSelf( _camera.position ).normalize() );
//				 ray.direction.normalize().multiplyScalar(valor);
//				 controls.object.position.addSelf(ray.direction);
//				break;
				
			case 'mousedown':
				
				
				
				$(WEBGL.getDomContainer()).removeClass('grabhand').css("cursor",'');
				
				var vector = new THREE.Vector3( params.xNorm, params.yNorm, 0.5 );
			 	projector.unprojectVector( vector, _camera );

			 	var ray = new THREE.Ray( _camera.position, vector.subSelf( _camera.position ).normalize() );
			
				///////////////////////SPRITEE////////////////////////////////////
				var sprt = CONTROLLER_JERARQUIA_SPACES.getTextXY(ray);
				if(sprt && params.kind == 'drag'){
					CONTROLLER_PAGE_STATE.showActiveSprite(sprt, params.x, params.y);
					this.noMoverse();
					lock = true;
					return -1;
				}
				
				lock = false;
				
				if (!_this.STATE.MOUSE){
					this.noMoverse();
					this.noAvanzar();
					return;
				}
				
				/////////////////////////FIN SPRITE //////////////////////////////////////
				if (params.kind == 'drag'){
					this.avanzar(-1);					
				}else if (params.kind == 'boton_derecho'){
					this.avanzar(1);
				}
				
				break;
				
			case 'mousemove':
				
				if (!_this.STATE.MOUSE || params.kind == 'rotation'){
					$(WEBGL.getDomContainer()).css("cursor",'').removeClass('grabhand');
					this.noMoverse();
					this.noAvanzar();
					return;
				}
				
				
				if (params.kind == 'no_button'){
					if (!lock)this.moverse(params.xNorm, params.yNorm);
					$(WEBGL.getDomContainer()).css("cursor",'').removeClass('grabhand');
					
				}else if (params.kind == 'drag'){
				//	this.moverse(params.xNorm, params.yNorm);				
					$(WEBGL.getDomContainer()).css("cursor",'').removeClass('grabhand');
						
				} else if (params.kind == 'rotation'){
					var x1 = params.xOld;
					var x2 = params.x;
					var y1 = params.yOld;
					var y2 = params.y;
					
					var ang1 = Math.PI/1080 * Math.abs(x1-x2);
					var ang2 = Math.PI/1080* Math.abs(y1-y2);
					 
					 if (x1 < x2){ang1 *= -1;}
					 if (y1 < y2){ang2 *= -1;}
					 
					personControls.rotarHorizontalmente(ang1);
					personControls.rotarPitch(ang2);
				}
			
				break;
				
			case 'mouseup' :
				
				SELECTED = 0;
				if (avanzando) this.noAvanzar();
				break;
				
			case 'mouseout' :
				
				SELECTED = 0;
				this.noMoverse();
				this.noAvanzar();
				break;
				
				
			case 'resize':
				
				var SCREEN_WIDTH = $(domContainer).width();
                var SCREEN_HEIGHT = $(domContainer).height();
                _camera.aspect = SCREEN_WIDTH/SCREEN_HEIGHT;
                _camera.updateProjectionMatrix();
                renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
                renderer.setScissor( 0,0, SCREEN_WIDTH, SCREEN_HEIGHT );
                renderer.setViewport( 0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
                contextViewport.resize();
                
				break;
			
			case 'keydown':
				//if (params.event.keyCode == 16){velocidadAvance *= 3;}
				if (personControls) personControls.keydown(params.event);
				
				
				break;
			case 'keyup':
				//if (params.event.keyCode == 16){velocidadAvance /= 3;}
				if (personControls) personControls.keyup(params.event);
				
				break;
				
			case 'panel_camara_desplazamiento' :
				
				var constante = 100;
				var radio = params.vector.length();
				var range = (radio/(params.width/2));
				Math.pow(range,4);
	
				var valor = range*constante;
				if(PERSONA){
					valor /= 50;
					personControls.desplazarXZ(params.vector, valor);//desplazar
				}else{
					valor /= 100;
					controls.desplazarXZ(params.vector, valor);//desplazar
				}
				
				break;
			
			case 'panel_camara_orientacion' :
				
				var vector = params.vector.negate();
				
				var constante = Math.PI/180;
				
				var ang1 = constante*(params.vector.x/(params.width/2));
				var ang2 = constante*(params.vector.z/(params.height/2));
				 
				//orientacion
				if(PERSONA){
					personControls.rotarHorizontalmente(ang1);
					personControls.rotarPitch(ang2);
				}else{
					controls.rotarHorizontalmente(ang1);
					controls.rotarPitch(ang2);
				}
				
				break;
				
			case 'panel_camara_zoom' :
				
				var valor = 0.5;
				if (params.action == 'zoomOut') valor *= -1;
				
				var nuevoValor = _camera.fov + valor;
				if ( nuevoValor < 70 && nuevoValor > 25 ){
					_camera.fov = nuevoValor;
					_camera.updateProjectionMatrix();
				}
				
//				personControls.object.translateZ(valor);
				break;
				
			case 'tree_select_building' :
				CONTROLLER_PAGE_STATE.focusDomContainer()
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showBuilding(params.nombreEdificio, false, false); //NO active level y NO unique (NO teletransporto)
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales, [], params.climbY, "level",null, false);
				break;
			case 'tree_select_level' :
				CONTROLLER_PAGE_STATE.focusDomContainer()
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, false); //NO active level y NO unique (NO teletransporto)
				//_this.cambiarUbicacion(params.nombreEdificio, params.nombreNivel, params.nombrePiso);
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales, [], params.climbY, "level",null, false);
				break;
			case 'tree_select_floor' :
				CONTROLLER_PAGE_STATE.focusDomContainer()
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, true); //active level y unique (teletransportacion)
				_this.teletransportar(params.nombreEdificio, params.nombreNivel, params.nombrePiso, null);
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales, [], params.climbY, "floor", null, false);
				break;
			case 'tree_select_space' :
				CONTROLLER_PAGE_STATE.focusDomContainer()
				
				var callback2 = function(){
					var pos = UTILS.toScreenXY($("#canvas_webgl"), params.centroid, _camera);
					
					var sp = CONTROLLER_JERARQUIA_SPACES.getSprite( params.nombreEdificio, params.nombreNivel, params.nombrePiso, params.idSpace);
					CONTROLLER_PAGE_STATE.showActiveSprite(sp, pos.x, pos.y);
				};
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, true);//active level y unique (teletransportacion)
				_this.teletransportar(params.nombreEdificio, params.nombreNivel, params.nombrePiso, params.idSpace);
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales, [], params.climbY, "space", callback2, false);
				break;
				
		}
		
	}
	
	//-----------------------------------------------------------
	//---------------------- ANIMATE ------------------------
	//-----------------------------------------------------------
	this.animate = function(){
		controls.update();	//actualiza los controles de la camara	
		personControls.update();
		
		
//		pointLight.position.x = _camera.position.x;
//		pointLight.position.z = _camera.position.z;
//		pointLight.position.y = _camera.position.y;
		
		pointLight.position.copy(controls.object.position);
		pointLight.position.y += 100;

		if (WEBGL.getRenderizarContexto())//renderizamos contexto?
		{
			renderer.enableScissorTest( false );
			renderer.clear();
			renderer.enableScissorTest( true );	
		}
		
		//<<RENDERIZAMOS PANTALLA PRINCIPAL>>
		renderer.render( _scene, _camera );
		//<<FIN RENDERIZAMOS PANTALLA PRINCIPAL>>
	
		if ( WEBGL.getRenderizarContexto())
		{
			contextViewport.animate();
		}
		
		//return {camera : _camera, scene : _scene};
	};
	
	
	
	
	
	
	
	

	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//---------------------- 1st person ------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	this.levelsShown = null;
	this.activeLevels = null;

	
	
//	var _ubicacionInicial = {edificio: "Alem", nivel: "0", piso: "CZ_PB"}; //el space va a ser el de referencia
	var _ubicacionInicial = {edificio: "Alem", nivel: "0", piso: "CA_PB", space: "18"}; //el space va a ser el de referencia
	var personControls = null;
	
	//TODO
	//TODO
	//TODO
	//TODO
	this.teletransportar = function(edificio, nivel, piso, space){
		var ed = edificio !== undefined ? edificio : _ubicacionInicial.edificio;
		var niv = nivel !== undefined ? nivel : _ubicacionInicial.nivel;
		var pi = edificio !== undefined ? piso : _ubicacionInicial.piso;
		var sp = edificio !== undefined ? space : _ubicacionInicial.space;
		
		_this.cambiarUbicacion(ed, niv, pi, sp);
		
//		var centroide = CONTROLLER_JERARQUIA_SPACES.getSpaceCentroid( _ubicacionInicial.edificio,  _ubicacionInicial.piso, null);//null == quiero el nodo de referencia del piso
//		_space = CONTROLLER_JERARQUIA_SPACES.getSpace( _ubicacionInicial.edificio,  _ubicacionInicial.piso, null);//null == quiero el nodo de referencia del piso
		var centroide = CONTROLLER_JERARQUIA_SPACES.getSpaceCentroid( ed, pi, sp);//null == quiero el nodo de referencia del piso
		_space = CONTROLLER_JERARQUIA_SPACES.getSpace( ed, pi, sp);//null == quiero el nodo de referencia del piso
		
		objPersona.position.x = centroide.x;
		objPersona.position.y = centroide.y + ALTURA_PERSONA;
		objPersona.position.z = centroide.z - 5;//-5 porque sino quedo arriba del sprite (OJO, ese -5 puede tirarme afuera del space, si el space es muy chico!!!)
	}
	
	//TODO
	//TODO
	//TODO
	//TODO
	this.cambiarUbicacion = function(edificio, nivel, piso, space){
		
		_ubicacionInicial.edificio = edificio;
		_ubicacionInicial.nivel = nivel;
		if (piso) _ubicacionInicial.piso = piso;
		if (space) _ubicacionInicial.space = space;
		
		CONTROLLER_JERARQUIA_SPACES.showLevel(_ubicacionInicial.edificio, _ubicacionInicial.nivel, true, true);
		
	}
	
	//TODO
	//TODO
	//TODO
	//TODO
	this.addPerson = function(){
		
		
		 
		 if (PERSONA){//camara
			 var SCREEN_WIDTH = $(domContainer).width();
			 var SCREEN_HEIGHT =  $(domContainer).height();
			 objPersona = new THREE.PerspectiveCamera( 45, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 1e8 );
			_camera = objPersona;
			
		 }else{//cubo que se mueve
			 var geometry = new THREE.CubeGeometry( 10,10,20 );
			 objPersona = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color:  0x00ff00 } ) );
			 
			 ALTURA_PERSONA = 10;
		 }
		 
		 this.teletransportar();
		 _scene.add( objPersona );
		 
		 
//		 personControls = new FlyControls( objPersona, domContainer); 
		 personControls = new FlyControlsPrueba( objPersona, domContainer); 
			personControls.movementSpeed = 500;
			personControls.rollSpeed = Math.PI /2;
			personControls.autoForward = false;
			personControls.dragToLook = false;
			
			//personControls.lookAtTarget(BUILDING_TARGET_POSITION);//entrada en alem //TODO que en el mapa venga la posicion inicial
			personControls.settearCondInic(); 
			personControls.controlsEnabled = true;
			
			personControls.sceneWrapper = _this;
			
			
			var path = _space.getPath();
			var str = "Edificio: "+ path.edificio + " nivel: "+ path.nivel+" piso: "+path.piso+ " ubicacion: "+((path.space == "")? " pasillo":path.space); 
			panelUbicacion.data(str);
	}
	
	
	var polygon = null;
	var _space = null;
	var _space2 = null;
	var _portal = null;
	var enPortal = false;
	var panelUbicacion = _webglObj.getDomContainerPanelController().getPanelUbicacion();
	
	//TODO
	//TODO
	//TODO
	//TODO
	this.managePositionChange = function(newPos){
			
			var inside = true;//por default
			var altura = 0;
			//$("#debugSpan").html('');
			
			if (_space){
				altura = _space.height ;
				
				var path = _space.getPath();
				var str = "Edificio: "+ path.edificio + " nivel: "+ path.nivel+" piso: "+path.piso+ " ubicacion: "+((path.space == "")? " pasillo":path.space); 
				panelUbicacion.data(str);
				
				console.log('espacio activo --> ', _space);
				
				var out = _space.outgoingPortals;
				if (!_portal){ //si no estoy en un portal.. me fijo si estoy pisando alguno
					for (var i =0 , l = out.length; i < l ; i++){
//						$("#debugSpan").prepend("probando---> "+i);
						
						if (out[i].dangling){ //si estoy en un dangling, cargo el nivel que le sigue
											  //cuando termina de cargarse, lo muestro, y muestro/oculto las paredes dependiendo del estado
											  //del wrapper 
							var path = out[i].getTargetId();
							var nivel = CONTROLLER_JERARQUIA_SPACES.getLevelName(path.edificio, path.piso);
							var callback = function(){
								var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(path.edificio, nivel, true, true);
								if (obj) ANIMATOR.reposicionarCamaraFromTree(BUILDING_TARGET_POSITION, obj.nivelesActuales , [], false, "level",null, false);
							};
							
							this.noMoverse();
							this.noAvanzar();
							 CONTROLLER_JERARQUIA_SPACES.loadLevel(path.edificio,nivel, callback);
							 portal = null;
							 return false;
						}
						
						if (isPointInPoly(out[i].contourScaled, objPersona.position)){
							_portal = out[i];
							 _space2 = out[i].getNextSpace(_space);	//$("#debugSpan").prepend("<br>prox space---> "+_space2.name+"<br>");
							 
							 
							break;
						}
					}
				}
				
				if (_portal){//si estoy en el portal
					if (keepsInside(_portal, newPos)){// me fijo que siga adentro
						
						inside = true;
						
						if (_portal.type == "ustair" || _portal.type == "dstair"){ //me fijo si el portal es una escalera
							altura =  _portal.interpolateHeight(objPersona.position, _space);
						}else{//no estoy en uan escalera
							if (keepsInside(_space2, newPos) && !keepsInside(_space, newPos)){//estoy en el portal, pero ya abandone el otro space
								_portal = null;
								_space = _space2; //el nuevo space es al que intente avanzar
								altura = _space.height ;
								checkLevelChange(_space);
							}
						}
						
					}else if ((_portal.type == "ustair" || _portal.type == "dstair") && insideStair()){
								//no caigo adentro del portal. estoy en el hueco de la escalera
								//estoy en el portal, pero no sobre alguno de los spaces
								//no me muevo (esto tiene que generar un problema :P )
						inside = false;
					}else{//ya sali del portal
						
						_portal = null;
						
						inside = keepsInside(_space2, newPos); 
						if (inside){ //si voy a pasar al otro space
							_space = _space2; //el nuevo space es al que intente avanzar
							altura = _space.height ;
							checkLevelChange(_space);
						}else{
							inside = keepsInside(_space, newPos);
						}
						
						
					}
				}else{//no estoy dentro de un portal, me estoy desplazando por un space
					portal = null;
					inside = keepsInside(_space, newPos);
				}
			}
//			$("#debugSpan").prepend("<hr>");
			newPos.y =  altura + ALTURA_PERSONA;
			//console.log("inside",inside)
			return inside;
		};
	
		
		//TODO
		//TODO
		//TODO
		//TODO
		//controlo que este en una escalera.. pero que no este sobre ninguno de los spaces que conecta,
		//si no hago este chequeo, podria ir a un space "saltando" por el costado de la escalera
		//inside stairs and outside spaces
		function insideStair(){
			
			if (_portal.type == "ustair" || _portal.type == "dstair" ){
				var a = isPointInPoly(_space.contour.points, objPersona.position);
				var b = isPointInPoly(_space2.contour.points, objPersona.position);
				//console.log('a',a,'b',b);
				return !(a || b ); //esta en el hueco de la escalera
			}
			return false;
		}
		
		//TODO
		//TODO
		//TODO
		//TODO
	function isPointInPoly(poly, pt){
		for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
			((poly[i].z <= pt.z && pt.z < poly[j].z) || (poly[j].z <= pt.z && pt.z < poly[i].z))
			&& (pt.x < (poly[j].x - poly[i].x) * (pt.z - poly[i].z) / (poly[j].z - poly[i].z) + poly[i].x)
			&& (c = !c);
		return c;
	}
	
	//TODO
	//TODO
	//TODO
	//TODO
	function checkLevelChange(space){
		console.log('checklevelchange')
		var path = space.getPath();
		if (_ubicacionInicial.edificio != path.edificio 
			||  _ubicacionInicial.nivel != path.nivel ){
			console.log('checklevelchange TRUEEEEEEEEE')
			_this.cambiarUbicacion(path.edificio, path.nivel, path.piso);
		}
	};
	
	//TODO
	//TODO
	//TODO
	//TODO
	function keepsInside(space, newPos){
		
	
		if (space instanceof Portal){
				var keepsInside = isPointInPoly(space.contourScaled, newPos);
		}else{
//			var keepsInside = isPointInPoly(space.contourScaled, newPos);
			var keepsInside = isPointInPoly(space.contour.points, newPos);
		}
		
		
		return keepsInside;
	}
	
	//vector 
	function toString(v){
//		return "x: "+v.x+" y:"+v.y+" z:"+v.z;
		return "x: "+v.x.toFixed(2);//+" y:"+v.y+" z:"+v.z;
	}
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//---------------------- 1st person ------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	
	
	
	
	
	
	
	
	
	
	//-----------------------------------------------------------
	//---------------------- CREAR MUNDO ------------------------
	//-----------------------------------------------------------
	//ahora el codigo comun esta en BuildingScene.js
	function crearMundo(scene){				
		_this.addPerson();
	}

	
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//---------------------- CREAR CAMARAS ------------------------
	//-----------------------------------------------------------
	//-----------------------------------------------------------
	//crea una FLY CAMERA en la escena pasada como parametro
	//<escena> : escena a la que se agregara la camara
	function crearCamaras(escena){
		
		var SCREEN_WIDTH = $(domContainer).width();
		var SCREEN_HEIGHT =  $(domContainer).height();
		//+++++++++ CAMARA CONTEXTO ++++++++++
		_camaraFlyContext = new THREE.PerspectiveCamera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 50, 1000000 );
		_camaraFlyContext.position.y = 300;
		
		controlsContext = new FlyControlsPrueba( _camaraFlyContext, domContainer, false);
		controlsContext.movementSpeed = 1000;
		controlsContext.rollSpeed = Math.PI /2;
		controlsContext.autoForward = false;
		controlsContext.dragToLook = false;
		controlsContext.rotarPitch(-Math.PI/2); 
		
		_camaraFlyContext.controls = controlsContext;
		//+++++++++ fin CAMARA CONTEXTO ++++++++++
		
		//+++++++++ CAMARA PRINCIPAL ++++++++++
		_camaraFly = new THREE.PerspectiveCamera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 1e8 );
//		_camaraFly.position.z = 500;
//		_camaraFly.position.y = 1500;
//		_camaraFly.position.x = 900;				
		_camaraFly.position.z = 200;
		_camaraFly.position.y = 300;
		_camaraFly.position.x = 900;				
					
		controls = new FlyControlsPrueba( _camaraFly, domContainer); 
		controls.movementSpeed = 1000;
		controls.rollSpeed = Math.PI /2;
		controls.autoForward = false;
		controls.dragToLook = false;
		
		controls.lookAtTarget(BUILDING_TARGET_POSITION);//entrada en alem //TODO que en el mapa venga la posicion inicial
		controls.settearCondInic(); 
		//+++++++++ fin CAMARA PRINCIPAL ++++++++++
		
		//+++++++++ Agregamos las camaras a la escena ++++++++++
		escena.add( _camaraFlyContext );
		escena.add( _camaraFly );
		//+++++++++ fin agregamos las camaras a la escena ++++++++++
		
		//+++++++++ Habilitamos los controles para la camara principal ++++++++++
		controls.controlsEnabled = false;
//		controls.controlsEnabled = true;
		//+++++++++ fin habilitamos los controles para la camara principal ++++++++++
		
		_camera = _camaraFly;
//		return _camaraFly;
	}
	
	
	//-----------------------------------------------------------
	//---------------------- CREAR LUCES ------------------------
	//-----------------------------------------------------------
	function crearLuces(escena){
            
		  ambientLight = new THREE.AmbientLight( 0x111111 );
          pointLight = new THREE.PointLight( 0x555555  );
          pointLight.position.y = 1000;
//          pointLight = new THREE.PointLight( 0x333333  );
          
//          directionalLight = new THREE.DirectionalLight( 0xaaaa99, 1.15);
          directionalLight = new THREE.DirectionalLight( 0xaaaa99, 1);
            directionalLight.position.x = 0;
            directionalLight.position.y = 1;
            directionalLight.position.z = 0;
            directionalLight.position.normalize();
            
            
            
            //escena.add( ambientLight );
            escena.add( pointLight );
            escena.add( directionalLight );
            
          
            return;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	//INIT
	//INIT
	//INIT
	//INIT
	//INIT
	crearCamaras(_scene);	
	crearLuces(_scene);
	crearMundo(_scene);
	//+++++++++ CONTEXTO ++++++++++
	var parameters = {webglObject : _webglObj,
					camera : _camaraFlyContext,
					width : 200,
					height : 200,
					posX : $(domContainer).width() - 200,
					posY : 0
				  };
	var contextViewport = new Contexto(parameters);
	//+++++++++ fin CONTEXTO ++++++++++
	
	this.context = contextViewport;
	//INIT
	//INIT
	//INIT
	//INIT
	//INIT
	
	
	
	
	
	
};